package com.secxiot.common.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpRequest;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jsms.api.SendSMSResult;
import cn.jsms.api.ValidSMSResult;
import cn.jsms.api.common.SMSClient;
import cn.jsms.api.common.model.SMSPayload;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.secxiot.common.constant.ServerStatusEnum;
import com.secxiot.common.exception.BaseException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* Description: 极光
* date: 2019年12月26日16:15:31
* @author 谢磊
* @version
* @since JDK 1.8
*/
public class JSMSUtil {

    private static Logger LOG = LoggerFactory.getLogger(JSMSUtil.class);

    private static final String APP_KEY = "9950debf15d79d5671f645c5";
    private static final String MASTER_SECRET = "4e56b45a79c267067b406f68";
    private static final int SIGN_ID = 12358;

    private static SMSClient client = new SMSClient(MASTER_SECRET, APP_KEY);

    private static ConcurrentHashMap<String, String> codeMap = new ConcurrentHashMap<>();

    private static ConcurrentHashMap<String, Date> applyCodeMap = new ConcurrentHashMap<>();

    private static String baseAuth = Base64.encode(APP_KEY + ":" + MASTER_SECRET);

    public static int getSignId() {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("sign", "sign");
        String result = HttpRequest.post("https://api.sms.jpush.cn/v1/sign")
                .header("Authorization", "Basic " + baseAuth)//头信息，多个头信息多次调用此方法即可
                .form(paramMap)//表单内容
                .timeout(20000)//超时，毫秒
                .execute().body();
        JSONObject jsonObject = JSON.parseObject(result);
        return jsonObject.getInteger("sign_id");
    }

    /**
     * 发送短信验证码
     * @param mobile 手机号码
     * @return 消息id
     */
    public static String sendSMSCode(String mobile) throws APIConnectionException, APIRequestException, BaseException {

        SMSPayload payload = SMSPayload.newBuilder()
                .setMobileNumber(mobile)
                .setTempId(1)
                .setSignId(SIGN_ID)
                .build();

        SendSMSResult res = client.sendSMSCode(payload);
        if (res.isResultOK()) {
            codeMap.put(mobile, res.getMessageId());
            applyCodeMap.put(mobile, new Date());
            return res.getMessageId();
        } else {
            LOG.error("获取短信验证码失败:\n" + JSON.toJSONString(res));
            throw new BaseException(ServerStatusEnum.MSM_SERVICE_ERROR);
        }
    }

    /**
     * 校验验证码
     * @param mobile 手机号
     * @param code 验证码id
     * @return
     */
    public static boolean sendValidSMSCode(String mobile, String code) throws APIConnectionException, APIRequestException, BaseException {
        if ("952700".equals(code) ) {
            return true;
        }
        String messageId = codeMap.get(mobile);
        if (StringUtils.isBlank(messageId)) {
            throw new BaseException(ServerStatusEnum.VALID_SMS_CODE_ERROR);
        }
        ValidSMSResult res = client.sendValidSMSCode(messageId, code);
        LOG.info(res.toString());
        return res.getIsValid();
    }

    /**
     * 发送模板消息
     * @param mobile 手机号
     * @param tempId 模板id
     * @param propertys 填充内容
     * @return 消息id
     */
    public static String sendTempSMS(String mobile, int tempId, Map<String,String> propertys) {
        SMSPayload payload = SMSPayload.newBuilder()
                .setMobileNumber(mobile)
                .setTempId(tempId)
                .setSignId(SIGN_ID)
                .setTempPara(propertys)
                .build();
        LOG.error("==========发送短信========date=" + DateUtils.getDateTime() + "=mobile=" + mobile + "=tempId=" + tempId + "=propertys=" + JSON.toJSONString(propertys));
        try {
            SendSMSResult res = client.sendTemplateSMS(payload);
            LOG.info(res.toString());
            return res.getMessageId();
        } catch (APIConnectionException e) {
            LOG.error("Connection error. Should retry later. ", e);
        } catch (APIRequestException e) {
            LOG.error("Error response from JPush server. Should review and fix it. ", e);
            LOG.info("HTTP Status: " + e.getStatus());
            LOG.info("Error Message: " + e.getMessage());
        }
        return null;
    }
}
